﻿#region << 文件说明 >>

/*----------------------------------------------------------------
 * 命名空间：Vampirewal.Core.WebApi
 * 唯一标识：44cb62b0-4926-4ecc-ad6a-5a1f1f736e59
 * 文件名：VampirewalCoreWebApiConfig
 *
 * 创建者：杨程
 * 电子邮箱：235160615@qq.com
 * 创建时间：2023/10/7 13:59:54
 * 版本：V1.0.0
 * 描述：
 *
 * ----------------------------------------------------------------
 * 修改人：
 * 时间：
 * 修改说明：
 *
 * 版本：V1.0.1
 *----------------------------------------------------------------*/

#endregion << 文件说明 >>

namespace Vampirewal.Core.WebApi;

/// <summary>
/// VampirewalCoreWebApi配置
/// </summary>
public sealed class VampirewalCoreWebApiConfig
{
    public VampirewalCoreWebApiConfig()
    {
    }

    internal IServiceCollection Services { get; set; }

    /// <summary>
    /// 是否启动webapi
    /// </summary>
    internal bool IsStartWebApi { get; set; } = false;

    #region 生成WebApi文档

    /// <summary>
    /// 是否生成webapi文档
    /// </summary>
    internal bool IsGeneratorWebApiDoc { get; set; } = false;

    /// <summary>
    /// 接口文档本地存储路径
    /// </summary>
    internal VampirewalApiDocOptions Option { get; set; }

    /// <summary>
    /// 启用WebApi文档
    /// <para><paramref name="默认地址"/>:http://*:9999/apidoc/index.html</para>
    /// </summary>
    /// <param name="option"></param>
    public void UseWebApiDoc(VampirewalApiDocOptions option)
    {
        Option = option;

        IsGeneratorWebApiDoc = true;

        if (option.IsGeneratToLocal)
        {
            if (!Directory.Exists(option.LocalPath))
            {
                Directory.CreateDirectory(option.LocalPath);
            }

            GeneratorApiDoc();

            File.WriteAllText($"{Option.LocalPath}//ApiDoc.html", ApiDocStr);
        }
    }

    internal void GeneratorApiDoc()
    {
        var content = ApiDocTemplate.Doc2.Replace("{{title}}", Option.Title);

        StringBuilder sbMenu = new StringBuilder();
        StringBuilder sbContent = new StringBuilder();
        foreach (var item in VampirewalCoreWebApiExtension.ApiDocInfos)
        {
            #region menu

            sbMenu.AppendLine("<li>");
            sbMenu.AppendLine($"    <h3 style=\"margin-bottom:10px; \" href=\"#{item.ControllerName}\">{item.Name}</h3>");
            sbMenu.AppendLine("    <ul class=\"submenu\">");
            sbMenu.AppendLine("        <li>");
            sbMenu.AppendLine("            <ul class=\"submenu\">");

            #endregion

            #region content

            if(string.IsNullOrEmpty(item.Description))
                sbContent.AppendLine($"<h2 id=\"{item.ControllerName}\">{item.Name}</h2>");
            else
                sbContent.AppendLine($"<h2 id=\"{item.ControllerName}\">{item.Name}&nbsp&nbsp&nbsp&nbsp{item.Description}</h2>");
            sbContent.AppendLine($"        <hr />");

            #endregion

            foreach (var me in item.Methods)
            {
                #region menu

                sbMenu.AppendLine($"                <li><a href=\"#{me.Name}-{me.RoutePath}\">{me.HttpType}-{me.Name}({me.RoutePath})</a></li>");

                #endregion

                #region content

                sbContent.AppendLine($"            <h3 id=\"{me.Name}-{me.RoutePath}\">{me.HttpType}-{me.Name}({me.RoutePath})</h3>");
                sbContent.AppendLine($"            <p>{me.Description}</p>");
                foreach (var par in me.Parameters)
                {
                    if(string.IsNullOrEmpty(par.Description))
                        sbContent.AppendLine($"                <h4 style=\"margin-left:30px; \" \">{par.Name}({par.Type})</h3>");
                    else
                        sbContent.AppendLine($"                <h4 style=\"margin-left:30px; \" \">{par.Name}({par.Type})&nbsp&nbsp&nbsp&nbsp{par.Description} </h3>");
                    //sbContent.AppendLine($"<p style=\"margin-left:30px; \">{par.Description}</p>");
                }
                sbContent.AppendLine($"        <hr style=\"width:400px;margin-left:0px; \"/>");

                #endregion
            }

            #region menu

            sbMenu.AppendLine("                        </ul>");
            sbMenu.AppendLine("                    </li>");
            sbMenu.AppendLine("                </ul>");
            sbMenu.AppendLine("            </li>");

            #endregion
        }

        content = content.Replace("{{menuList}}", sbMenu.ToString()).Replace("{{content}}", sbContent.ToString());

        ApiDocStr = content;
    }

    internal string ApiDocStr { get; set; }

    #endregion

    #region 设置监听IP和端口号

    internal string Url { get; set; }

    /// <summary>
    /// 设置监听IP地址和端口号
    /// </summary>
    /// <returns></returns>
    public VampirewalCoreWebApiConfig SetIpPort(string ip, int port)
    {
        Url = $"http://{ip}:{port}/";

        return this;
    }

    #endregion

    /// <summary>
    /// 初始化标准配置
    /// </summary>
    /// <returns></returns>
    internal static VampirewalCoreWebApiConfig InitConfig()
    {
        return new VampirewalCoreWebApiConfig()
        {
            Url = $"http://localhost:9999/",
            IsStartWebApi = true,
            Services = new ServiceCollection(),
        };
    }
}

/// <summary>
/// ApiDoc配置项
/// </summary>
public sealed class VampirewalApiDocOptions
{
    /// <summary>
    /// 标题
    /// </summary>
    public string Title { get; set; }

    /// <summary>
    /// 版本
    /// </summary>
    public string Version { get; set; }

    /// <summary>
    /// 文档本地路径
    /// </summary>
    public string LocalPath { get; set; }

    internal bool IsGeneratToLocal
    {
        get
        {
            return string.IsNullOrEmpty(LocalPath) ? false : true;
        }
    }
}

internal class ApiDocControllerInfo
{
    public string Name { get; set; }

    public string ControllerName { get; set; }

    public string Description { get; set; }

    public List<ApiDocMethodInfo> Methods { get; set; }
}

internal class ApiDocMethodInfo
{
    public string Name { get; set; }

    public string Description { get; set; }

    public string RoutePath { get; set; }

    public HttpMethod HttpType { get; set; }

    public List<ApiDocMethodParameter> Parameters { get; set; }
}

internal class ApiDocMethodParameter
{
    public string Name { get; set; }

    public string Description { get; set; }

    public string Type { get; set; }
}